from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import login_required
from google.appengine.api import users
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from model import *
from record import TableRecord
import os, StringIO, csv, datetime,logging

def list_to_csv(rows):
    """convert a a list of rows into csv text"""
    out = StringIO.StringIO()
    writer = csv.writer(out, lineterminator='\n')
    writer.writerow(rows[0])
    for row in rows[1:]:
        writer.writerow(row)
    csv_text = out.getvalue()
    out.close()
    return csv_text

def insert_impact_record(record):
    '''insert a record'''
    i = TableRecord(None, Impact.fields().keys(), ['ctime', 'mtime', 'user'])
    for fld in Impact.fields().keys():
        i[fld] = record[fld]
    i.insert(Impact)
    
def import_impact_record(record):
    record = clean_impact_record(record)
    if record.get('key'):
        #existing record, update
        update_impact_record(record)
    else:
        insert_impact_record(record)
        
def update_impact_record(record):
    '''update a record'''
    
    i = TableRecord(record['key'], Impact.fields().keys(), ['ctime', 'mtime', 'user'])
    for fld in Impact.fields().keys():
        i[fld] = record[fld]
    i.save_changes()
    

def clean_impact_record(record):
    '''clean a record, process values'''
    for fld in Impact.fields().keys():
        v = record.get(fld)
        if fld in ['x', 'y']:
            try:
                v = float('%.6f' % float(record[fld]))
            except:
                v = -1
        elif fld in ['roadway', 'garage', 'adaparking', 'sidewalk']:
            if v=='TRUE':
                v = True
            else:
                v = False
        elif fld in ['start_date', 'end_date']:
            m, d, y = v.split('/')
            v = datetime.datetime(int(y), int(m), int(d))
        record[fld] = v
    return record

def delete_impact_table():
        '''delete all the tables'''
        db.delete(Impact.all())
        db.delete(TrackChange.all())

def backup_impact_table():
    '''save a csv file to a blobstore'''
    out = StringIO.StringIO()
    writer = csv.writer(out, lineterminator='\n')
    fields = Impact.fields().keys()
    writer.writerow(fields)
    q = Impact.all()
    for r in q:
        row = []
        for fld in fields:
            row.append(getattr(r, fld))
        writer.writerow(row)
    csvfile = CsvFile()
    csvfile.csvfile = db.Blob(out.getvalue())
    csvfile.name = 'backup'
    csvfile.put()


class ManageHandler(webapp.RequestHandler):
    """the admin page: manage
    the date must be in the format of yyyy-mm-dd hh:mm
"""
        
    def upload_impact_list(self):
        backup_impact_table()
        csvfile = CsvFile()
        csvfile.name = 'upload'
        csvfile.csvfile = db.Blob(self.request.get('upload'))
        
        csvfile.put()

        f = StringIO.StringIO(csvfile.csvfile)
        reader = csv.reader(f)
        #load the data
        h = reader.next()
        for l in reader:
            fe = dict(zip(h,l))
            import_impact_record(fe)
        message = 'Impact Records successfully uploaded.'
        values = {'table': 'Impact Table', 'message': message}
        path = os.path.join(os.path.dirname(__file__), 'manage_message.html')
        self.response.out.write(template.render(path, values)) 
    def download_impact_list(self):
        """download all impact records as csv file"""
        rows = []
        fields = Impact.fields().keys()
        rows.append(['key'] + fields)
        q = Impact.all()
        for r in q:
            row = [str(r.key())]
            for fld in fields:
                v = getattr(r, fld)
                if fld in ['start_date', 'end_date']:
                    v = '%s/%s/%s' % (v.month, v.day, v.year)
                    
                row.append(v)
                
            rows.append(row)
        csv_text = list_to_csv(rows)
        self.response.headers["Content-Type"] = "text/csv"
        self.response.headers["Content-Disposition"] = "attachment;filename=download.csv"
        self.response.out.write(csv_text)
    def delete_impact_list(self):
        logging.info('deleting pm list')
        try:
            delete_impact_table()
            message = 'Impact Table successfully deleted.'
        except:
            message = 'Failed to delete Impact Table.'
        values = {'table': 'Impact Table', 'message': message}
        path = os.path.join(os.path.dirname(__file__), 'manage_message.html')
        self.response.out.write(template.render(path, values)) 
        
    def delete_pm_list(self):
        logging.info('deleting pm list')
        try:
            db.delete(ListTable.all().filter('list_name =', 'pm'))
            message = 'PM Table successfully deleted.'
        except:
            message = 'Failed to delete PM Table.'
        values = {'table': 'PM Table', 'message': message}
        path = os.path.join(os.path.dirname(__file__), 'manage_message.html')
        self.response.out.write(template.render(path, values))  
            
    def download_pm_list(self):
        rows = []
        rows.append(['value', 'list_name'])
        for r in ListTable.all().filter('list_name =', 'pm'):
            rows.append([r.value, r.list_name])
        csv_text = list_to_csv(rows)
        self.response.headers["Content-Type"] = "text/csv"
        self.response.headers["Content-Disposition"] = "attachment;filename=download.csv"
        self.response.out.write(csv_text)
                 
    def upload_pm_list(self):
        #upload the pm list, delete the pm entries from the list then add the new ones from the csv file.
        logging.info('uploading pm list')
        #save the old list in case the uploading failed
        old_list = []
        for r in ListTable.all().filter('list_name =', 'pm'):
            old_list.append({'value': r.value, 'list_name': r.list_name})
        
        
        
        csvfile =  self.request.get('upload')
        f = StringIO.StringIO(csvfile)
        reader = csv.reader(f)
        #load the data
        h = reader.next()
        
        new_list = []
        for l in reader:
            fe = dict(zip(h,l))
            
            lt = ListTable(value=fe['value'], list_name = fe['list_name'])
            new_list.append(lt)
        db.delete(ListTable.all().filter('list_name =', 'pm'))
        try:
            db.put(new_list)
            message = 'PM list is successfully uploaded.'
        except:
            #in case it failed, put the old values back.
            olds = []
            for r in old_list:
                lt = ListTable(value=fe['value'], list_name = fe['list_name'])
                olds.append(lt)
            message = 'PM list upload failed. Old values were deleted.'
            db.put(olds)
            message = 'PM list upload failed. Old values remained.'
            
        values = {'table': 'PM Table', 'message': message}
        path = os.path.join(os.path.dirname(__file__), 'manage_message.html')
        self.response.out.write(template.render(path, values))  
            
            
        
#    def upload_csv_backup(self):
#        self.backup_csv()
#        csvfile = CsvFile()
#        csvfile.name = 'upload'
#        csvfile.csvfile = db.Blob(self.request.get('upload'))
#        
#        csvfile.put()
#
#        f = StringIO.StringIO(csvfile.csvfile)
#        reader = csv.reader(f)
#
#        #empty the table
#        q = Impact.all()
#        db.delete(q)
#        
#        db.delete(TrackChange.all())
#        #load the data
#        h = reader.next()
#        for l in reader:
#            fe = dict(zip(h,l))
#            i = Impact()
#            for k in h:
#                v = fe[k]
#                if k in ['roadway', 'adaparking', 'garage', 'sidewalk']:
#                    v = (v=='TRUE')
#                if k in ['x', 'y']:
#                    v = float(v)
#                if k in ['start_date', 'end_date']:
#                    dp = v.split()[0]
#                    m, d, y = dp.split('/')
#                    v = datetime.datetime(int(y), int(m), int(d))
#                setattr(i, k, v)
#            i.put()


#    def download_csvfile(self):
#        k = self.request.get('filekey')
#        if k:
#            csvfile = db.get(k)
#            self.response.headers["Content-Type"] = "text/csv"
#            self.response.headers["Content-Disposition"] = "attachment;filename=download.csv"
#            self.response.out.write(csvfile.csvfile)
            
        
    @login_required
    def get(self):
        if users.get_current_user():
            action = self.request.get('action')
            if action=='download':
                self.download_csv()
            elif action=='downloadcsv':
                self.download_csvfile()
            elif action=='delete':
                self.delete_all()
            elif action=='delete_impact_list':
                self.delete_impact_list()
            elif action=='download_impact_list':
                self.download_impact_list()
            elif action=='impact_list':
                 values = {
                   'upload_url': '/manage?action=upload_impact_list',
                  'download_url': '/manage?action=download_impact_list',
                  'delete_url': '/manage?action=delete_impact_list',
                  'table': 'Impact Table'
                }

                 path = os.path.join(os.path.dirname(__file__), 'manage_table.html')
                 self.response.out.write(template.render(path, values))
            elif action=='delete_pm_list':
                self.delete_pm_list()
            elif action=='download_pm_list':
                self.download_pm_list()
            elif action=='pm_list':
                 values = {
                   'upload_url': '/manage?action=upload_pm_list',
                  'download_url': '/manage?action=download_pm_list',
                  'delete_url': '/manage?action=delete_pm_list',
                  'table': 'Project Manager Table'
                }

                 path = os.path.join(os.path.dirname(__file__), 'manage_table.html')
                 self.response.out.write(template.render(path, values))
                
            else:
                 values = {'buttons': [{'url': '/manage?action=impact_list', 'text': 'Impact List'},
                           {'url': '/manage?action=pm_list', 'text': 'PM List'}]}
                 path = os.path.join(os.path.dirname(__file__), 'manage_panel.html')
                 self.response.out.write(template.render(path, values))                
                
#                 values = {
#                   'upload_url': '/manage?action=upload',
#                  'download_url': '/manage?action=download',
#                  'delete_url': '/manage?action=delete',
#                  'upload_list_url': '/manage?action=upload_list'
#                }
#
#                 path = os.path.join(os.path.dirname(__file__), 'manage.htm')
#                 self.response.out.write(template.render(path, values))
    def post(self):
        """Handle the upload"""
        if users.get_current_user():
            
            action = self.request.get('action')
#            if action=='upload':
#                self.upload_csv()
            if action=='upload_pm_list':
                self.upload_pm_list()
            elif action=='upload_impact_list':
                self.upload_impact_list()